#!/usr/bin/env bash
# SPDX-License-Identifier: MulanPSL-2.0+
# Copyright (c) 2024 Huawei Technologies Co., Ltd. All rights reserved.

rpm_download() {
    local rpm_name=$1
    local rpm_path=$2
    yumdownloader --quiet --disablerepo="*" --enablerepo="$SOURCE_REPO_NAME" "${rpm_name%.rpm}" --destdir="$rpm_path"
}

rpm_unpack() {
    local rpm_path=$1
    local rpm_fs_dir=$2
    rpm2cpio $rpm_path | cpio -di --quiet --directory=$rpm_fs_dir
}

rpm_hash() {
    local rpm_name=$1
    local rpm_fs_dir=$2
    local hash_value=$($EPKG_HASH_EXEC "$rpm_fs_dir")
    pkg_hash_dict[$rpm_name]=$hash_value
}

rpm_hash_pipeline() {
    local rpm_name=$1
    local rpm_path=$2

    # Init source dir
    local rpm_source_dir=$X2EPKG_SOURCE_DIR/$rpm_name

    # Init convert dir
    local rpm_convert_dir=$X2EPKG_DEST_DIR/$rpm_name
    local rpm_fs_dir=$rpm_convert_dir/fs
    local rpm_info_dir=$rpm_convert_dir/info
    if [[ -d $rpm_fs_dir ]]; then
        echo "$rpm_name fs dir exist: $rpm_fs_dir"
        return
    fi
    mkdir -p $rpm_fs_dir
    mkdir -p $rpm_info_dir

    # Download
    if [ -z "$rpm_path" ]; then
        rpm_path=$rpm_source_dir/$rpm_name
        rpm_download "$rpm_name" "$rpm_source_dir"
    fi

    # Unpack
    rpm_unpack "$rpm_path" "$rpm_fs_dir"
    
    # Hash
    rpm_hash "$rpm_name" "$rpm_fs_dir"
}

rpm_info_query() {
    local rpm_path=$1
 
    while IFS=':' read -r key value; do
        key=$(echo "$key" | xargs)
        value=$(echo "$value" | xargs)
        case "$key" in
            Name)
                name="$value"
                ;;
            Version)
                version="$value"
                ;;
            Release)
                release=$(echo "$value" | cut -d'.' -f1)
                dist=$(echo "$value" | cut -d'.' -f2)
                ;;
            Architecture)
                arch=$value
                ;;
        esac
    done <<< "$(rpm -qi $rpm_path)"
}

generate_package_json() {
    local rpm_name=$1
    local rpm_requires=$2
    local rpm_provides=$3
    local rpm_pkg_hash=${pkg_hash_dict[$rpm_name]}

    local json=$(jq -n \
		--arg name "$name" \
		--arg version "$version" \
		--arg release "$release" \
		--arg dist "$dist" \
		--arg arch "$arch" \
        --arg hash "$rpm_pkg_hash" \
		'{name: $name, version: $version, release: $release, dist: $dist, arch: $arch, hash: $hash}'
	)

    # "depends: [{}]"
    declare -a depends_array=()
    for require_name in "${!depends[@]}"; do
        require_name=${require_name}.rpm
        if [[ -v pkg_hash_dict[$require_name] ]]; then
            echo "$rpm_name hash value exist"
        else 
            rpm_hash_pipeline "$require_name"
        fi

        local require_hash=${pkg_hash_dict[$require_name]}
        depends_array+=("{\"hash\": \"$require_hash\", \"pkgname\": \"$require_name\"}")
    done
    json=$(echo "$json" | jq --argjson depends "$(printf '%s\n' "${depends_array[@]}" | jq -s '.')" '. + {depends: $depends}')

    # "requires": []
    requires_json=$(echo "$rpm_requires" | jq -R . | jq -s .)
    json=$(echo "$json" | jq --argjson requires "$requires_json" '. + { "requires": $requires }')

    # "provides: []"
    provides_json=$(echo "$rpm_provides" | jq -R . | jq -s .)
    json=$(echo "$json" | jq --argjson provides "$provides_json" '. + { "provides": $provides }')

    echo "$json" > $X2EPKG_DEST_DIR/$rpm_name/info/package.json
}

rpm_convert_json() {
    local rpm_name=$1
    local rpm_path=$2

    # Hash pipeline
    rpm_hash_pipeline "$rpm_name" "$rpm_path"

    # Get Provide
    local rpm_provides=$(rpm -q --provides $rpm_path | sort -u)

    # Get_requires
    declare -A depends
    local rpm_requires=$(repoquery --quiet --requires $rpm_path)
    while IFS= read -r require; do
        # pass rpmlib(*)
        if [[ $require == rpmlib* ]]; then
            continue
        fi

        require_pkgs=$(repoquery --quiet --whatprovides "$require" --qf='%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}')
        if [ -n "$require_pkgs" ]; then
            while IFS= read -r require_pkg; do
                depends["$require_pkg"]=1
            done <<< "$require_pkgs"
        else
            echo "Not found require_pkgs: $require"
        fi
    done <<< "$rpm_requires"

    # Generate Package json
    generate_package_json "$rpm_name" "$rpm_requires" "$rpm_provides"
}

epkg_compress() {
    local rpm_name="$1"
    local epkg_hash=${pkg_hash_dict[$rpm_name]}
    local compress_file=${X2EPKG_EPKG_DIR}/${epkg_hash}__${name}__${version}__${release}.${dist}.epkg
    local rpm_convert_dir=$X2EPKG_DEST_DIR/$rpm_name
    touch ${rpm_convert_dir}/info/{buildinfo.json,files,runtimePhase.sh}

    mkdir -p $X2EPKG_EPKG_DIR
    tar --zstd -cf $compress_file -C ${rpm_convert_dir} .
}

rpm_convert() {
    local rpm_path=$1

    local name=
    local version=
    local release=
    local dist=
    local arch=

    rpm_info_query $rpm_path
    local rpm_name=${name}-${version}-${release}.${dist}.${arch}.rpm
    echo "Start convert: $rpm_name, name: $name, version: $version, release: $release, dist: $dist, arch: $arch"

    rpm_convert_json "$rpm_name" "$rpm_path" "$rpm_info_dir"
    epkg_compress "$rpm_name"
    # pkgname: 删除.rpm
}
